/*
   file : exesql.c
    词语、语法解析完毕开始执行相应的操作的函数的具体实现
   University of Jiangsu
   memoryDB      2010.6
 */



#include "exesql.h"
#include "shm_interface.h"

int DisplayRecord(Record *record,int sockfd)
{
	char newline[MAX_COMMAND],temp[MAX_COMMAND];
	bzero(newline,MAX_COMMAND);
	bzero(temp,MAX_COMMAND);
	
	Field *f;
	for(f=record->Field_list;f!=NULL;f=f->Next_Field){
		switch(f->date_type){
			case INTX:sprintf(temp,"%d|",f->Int_Val);break;
			case DOUBLEX:sprintf(temp,"%f|",f->Double_Val);break;
			case STRINGX:sprintf(temp,"%s|",f->Str_Val);break;
		}
		strcat(newline,temp);
		bzero(temp,MAX_COMMAND);
	}
	strcat(newline,"\n");
	write(sockfd,newline,strlen(newline));
	
	return 0;
}

/*
   返回-1表示表不存在
   返回0正常
 */
int ExeSelect(Select *select_sentence,int sockfd)
{
	char newline[MAX_COMMAND],temp[MAX_COMMAND];
	bzero(newline,MAX_COMMAND);
	bzero(temp,MAX_COMMAND);
	
	int tb_id;
	if((tb_id=ExistTable(select_sentence->Select_list->Table_Name)) == -1){
		strcpy(newline,"table not exist\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}

	record_add addr = Get_First_Record(tb_id);
    record_add old_addr = addr;
    
	Record *Cmp_field_list = malloc(sizeof(Record));
    Init_Record(Cmp_field_list);
    Get_Cmp_Field(select_sentence->Select_where,Cmp_field_list);

	sprintf(newline,"--------------------results--------------------\n");
	Field *f_temp=select_sentence->Select_list->Field_list;
	while(1){
		if(f_temp == NULL)
		  break;
		sprintf(temp,"%s|",f_temp->Field_Name);
		strcat(newline,temp);
		bzero(temp,MAX_COMMAND);
		f_temp=f_temp->Next_Field;
	}
	strcat(newline,"\n");
	write(sockfd,newline,strlen(newline));
	
	int count=0;
	for(;addr.p_blk!=NULL;old_addr = addr){
		if(Cmp_field_list->Field_list)
		  addr = Get_Record(addr,Cmp_field_list);
		else
		  addr = Get_Next_Add(addr);
		
		if(DoWhere(select_sentence->Select_list->Table_Name,select_sentence->Select_where,Cmp_field_list)){
			count++;
			Record *record = malloc(sizeof(Record));
			Init_Record(record);
			Field *f=select_sentence->Select_list->Field_list;
			int i;
			for(i=0;i<select_sentence->Select_list->Field_num;i++,f=f->Next_Field){
				Field *f_2=malloc(sizeof(Field));
				Init_Field(f_2);
				strcpy(f_2->Field_Name,f->Field_Name);
				AddField_Record(f_2,record);
			}
			Get_Record(old_addr,record);
			DisplayRecord(record,sockfd);
			Free_Record(record);
		}
		
	}
	
	if(count == 0){ 
		sprintf(newline,"no record\n");
		strcat(newline,"-----------------------------------------------\n");
		write(sockfd,newline,strlen(newline));
		return 0;
	}

	sprintf(newline,"\ntotal record: %d\n",count);
	strcat(newline,"---------------------------------------------------\n");
	write(sockfd,newline,strlen(newline));
	return 0;
}

/*
   -1代表创建表失败
   0代表正常
 */
int ExeCreateTable(Create_Table *create_sentence, int sockfd)
{
	char newline[MAX_COMMAND];
	Field *f = create_sentence->Tab->Field_list;
      
	if(CreateTable(create_sentence->Tab)){
		strcpy(newline,"create table failed\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}
	strcpy(newline,"create table ok\n");
	write(sockfd,newline,strlen(newline));
	return 0;
}

int ExeUpdate(Update *Update_sentence,int sockfd)
{
	char newline[MAX_COMMAND];
	Field *f;
	Field *cf;
	Record *rec;
	
	int tb_id;
	if((tb_id=ExistTable(Update_sentence->Tab->Table_Name)) == -1){
		strcpy(newline,"tables not exist\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}
	
	record_add addr,old_addr;
	addr = Get_First_Record(tb_id);
    old_addr=addr;
    Record *Cmp_field_list = malloc(sizeof(Record));
    Init_Record(Cmp_field_list);
	
	Get_Cmp_Field(Update_sentence->Select_where,Cmp_field_list);
	int num = Get_Field_Num(tb_id);

	int count=0,i=0;
	for(;addr.p_blk!=NULL;old_addr = addr){  
		if(Cmp_field_list->Field_list)
		  addr = Get_Record(addr,Cmp_field_list);
		else
		  addr = Get_Next_Add(addr);
		if(DoWhere(Update_sentence->Tab->Table_Name,Update_sentence->Select_where,Cmp_field_list)){
			count++;
			//获得更新的字段，并组成一条完整的记录rec
			rec=malloc(sizeof(Record));
			Init_Record(rec);
			for(i=0;i<num;i++){
				f = malloc(sizeof(Field));
				Init_Field(f);
				Get_Field_Content(old_addr,i,f); 
				for(cf=Update_sentence->Tab->Field_list;cf;cf=cf->Next_Field){
					if(!strcmp(cf->Field_Name,f->Field_Name)){
						Field *ff = malloc(sizeof(Field));
						*ff = *cf; 
						ff->Next_Field =NULL;
						AddField_Record(ff,rec);
						break;
					}
				}
				if(!cf)
				  AddField_Record(f,rec);     
			}
			Update_Record(old_addr,rec);
			Free_Record(rec);
		}
	}
	sprintf(newline,"%d records affected\n",count);
	write(sockfd,newline,strlen(newline));
	return 0;
}

int ExeInsect(Insect *insect_sentence,int sockfd)
{
	char newline[MAX_COMMAND];
	char str[MAX_LINE];
	bzero(str,MAX_LINE);
	
	Record *rec = malloc(sizeof(Record));
	rec->Field_list = insect_sentence->Tab->Field_list;
	rec->Feild_num = insect_sentence->Tab->Field_num;
    rec->Last_field = insect_sentence->Tab->Last_Field;
	Combine_Record_To_String(rec,str);
    
	int tb_id;
	if((tb_id=ExistTable(insect_sentence->Tab->Table_Name)) == -1){
		strcpy(newline,"tables not exist\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}

	if(insert_record(str,tb_id) == -1){
		strcpy(newline,"insert failed\n");
		write(sockfd,newline,strlen(newline));
		return -2;
	}
	strcpy(newline,"insert ok\n");
	write(sockfd,newline,strlen(newline));
	return 0;
}

int ExeDelete(Delete *delete_sentence,int sockfd)
{
	char newline[MAX_COMMAND];
    Field *cf;
	Record *rec;

	int tb_id;
	if((tb_id=ExistTable(delete_sentence->Select_Table->Table_Name)) == -1){
		strcpy(newline,"tables not exist\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}

	record_add addr,old_addr;
	addr = Get_First_Record(tb_id);
    old_addr = addr;

    Record *Cmp_field_list = malloc(sizeof(Record));
    Init_Record(Cmp_field_list);
    Get_Cmp_Field(delete_sentence->Select_where,Cmp_field_list);
	int count=0;
	for(;addr.p_blk;old_addr=addr){
		if(Cmp_field_list->Field_list)
		  addr = Get_Record(addr,Cmp_field_list);
		else
		  addr = Get_Next_Add(addr);
		if(DoWhere(delete_sentence->Select_Table->Table_Name,delete_sentence->Select_where,Cmp_field_list)){
			count++;
			Delete_Record(old_addr);
		}
	}
	sprintf(newline,"%d records affected\n",count);
	write(sockfd,newline,strlen(newline));
	return 0;
}

int ExeDropTable(Drop_Table *drop_sentence,int sockfd)
{
	char newline[MAX_COMMAND];
	int tb_id;
	if((tb_id=ExistTable(drop_sentence->name)) == -1){
		strcpy(newline,"tables not exist\n");
		write(sockfd,newline,strlen(newline));
		return -1;
	}
	
	printf("confirm?y/n");
	char temp;
	scanf("%c",&temp);
	getchar();
	if(temp=='y' || temp=='Y'){
		delete_tb(tb_id);
		save_all(1);
		strcpy(newline,"drop table ok\n");
		write(sockfd,newline,strlen(newline));
	}
	return 0;
}
